Under current law, a conviction of “Simple Possession” of drugs (21a-279(d)) within 1,500 feet of a school or day care center carries a mandatory minimum two year prison term. A conviction of “Possession with Intent to Sell” (21a-278(b)) drugs within 1,500 feet of a school, day care center, or public housing carries a mandatory minimum three year prison term.

Governor Dannel Malloy has proposed Bill 952 to remove mandatory minimums for the possession of drugs (21a-279(d)) because he states that the two year mandatory prison sentence in urban areas “has had an extraordinarily impact” on African-American and Latino communities. Almost all of the area of New Haven, Hartford, Bridgeport and most other densely populated cities in the state are within a “school zone” while the vast majority of suburban towns are not.

Earlier this month Malloy said 64 percent of those charged with drug possession in school zones are minorities, according to the Sentencing Commission. The Connecticut Judicial Branch could only provide raw data on convictions stretching back to 1999. We looked at arrests and convictions data for the following charges:

This analysis was used for the story on TrendCT.org based on arrests and convictions data from the Connecticut Judicial Branch.


Visualizing the zones where suspects can get charged for 21a-279d

There are more than 3,000 day cares centers and schools across Connecticut. A 1,500 radius around each one would look like this.

## rgeos version: 0.3-11, (SVN revision 479)
##  GEOS runtime version: 3.4.2-CAPI-1.8.2 r3921 
##  Linking to sp version: 1.1-0 
##  Polygon checking: TRUE 
## 
## Checking rgeos availability: TRUE
## rgdal: version: 0.9-3, (SVN revision 530)
##  Geospatial Data Abstraction Library extensions to R successfully loaded
##  Loaded GDAL runtime: GDAL 1.11.2, released 2015/02/10
##  Path to GDAL shared files: /Library/Frameworks/R.framework/Versions/3.2/Resources/library/rgdal/gdal
##  Loaded PROJ.4 runtime: Rel. 4.9.1, 04 March 2015, [PJ_VERSION: 491]
##  Path to PROJ.4 shared files: /Library/Frameworks/R.framework/Versions/3.2/Resources/library/rgdal/proj
##  Linking to sp version: 1.1-0 
## 
## Attaching package: 'dplyr'
## 
## The following objects are masked from 'package:rgeos':
## 
##     intersect, setdiff, union
## 
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## 
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
## OGR data source with driver: ESRI Shapefile 
## Source: "shapes", layer: "finaltowns"
## with 169 features
## It has 22 fields
## OGR data source with driver: ESRI Shapefile 
## Source: "shapes", layer: "finalschoolsdaycares"
## with 169 features
## It has 25 fields
## OGR data source with driver: ESRI Shapefile 
## Source: "shapes", layer: "finalzones"
## with 169 features
## It has 28 fields

We calculated the area of the school and day care zones in each city versus the area of the entire town according to the US Census. Dense urban areas like Hartford, New Haven and Bridgeport had a higher percent of those mandatory minimum zones within town borders.

Note: Calculations for towns along the coast will be off because the census borders for the towns sometimes extends out into the water.

The relationship between number of arrests and percent of town in a buffer

library(ggplot2)
library(stringr)
library(plotly)
## Loading required package: RCurl
## Loading required package: bitops
## Loading required package: RJSONIO
arrests_new <- read.csv("arrests_h.csv", stringsAsFactors=FALSE)
pop <- read.csv("ctpop.csv", stringsAsFactors=FALSE)
newnames <- read.csv("townlist.csv", stringsAsFactors=FALSE)

colnames(newnames) <- c("TOWN", "Town.Name")
arrests_new <- left_join(arrests_new, newnames)
## Joining by: "TOWN"
arr_charges <- data.frame(table(arrests_new$Town.Name, arrests_new$ORIGINAL_STATUTE))
arr_charges_d <- filter(arr_charges, Var2=="21a-279(d)")

colnames(arr_charges_d) <- c("Town", "Statute", "Arrests")
arr_charges_d$Town <- str_to_title(arr_charges_d$Town)
arr_charges_d <- left_join(arr_charges_d, d279)
## Joining by: "Town"
arr_charges_d <- na.omit(arr_charges_d)

arr_charges_d[2] <- NULL
arr_charges_d[3] <- NULL
arr_charges_d[3] <- NULL


colnames(pop) <- c("Town", "Population")
pop$Town <- str_to_title(pop$Town)
arr_charges_d <- left_join(arr_charges_d, pop)
## Joining by: "Town"
arr_charges_d$Arrests.Per.Capita <- (arr_charges_d$Arrests/arr_charges_d$Population)*1000
arr_charges_d$Arrests.Per.Capita <- round(arr_charges_d$Arrests.Per.Capita, digits=2)

daplot <- ggplot(arr_charges_d, aes(x=Percent.of.town.in.buffer, y=Arrests)) +
  geom_point(aes(text=Town)) +
  geom_smooth(method=lm, formula = y ~ poly(x, 3), size=1) +
  theme_minimal() +
  ggtitle("Number of arrests versus percent of Buffer zone") %>%
  labs(x="Percent of town in buffer", y="Arrests for 279(d) since 1999")

oy <- plotly()
oy$ggplotly(daplot, session="knitr", kwargs=list(layout=list(hovermode="closest", filename="buffer-279d", fileopt="overwrite")))



arr_lm3 <- lm(arr_charges_d$Percent.of.town.in.buffer ~ poly(arr_charges_d$Arrests, 3))
summary(arr_lm3)
## 
## Call:
## lm(formula = arr_charges_d$Percent.of.town.in.buffer ~ poly(arr_charges_d$Arrests, 
##     3))
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -23.971  -5.272  -2.614   3.696  30.349 
## 
## Coefficients:
##                                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                      10.9500     0.6214  17.621  < 2e-16 ***
## poly(arr_charges_d$Arrests, 3)1  87.0936     8.0786  10.781  < 2e-16 ***
## poly(arr_charges_d$Arrests, 3)2 -33.0493     8.0786  -4.091 6.70e-05 ***
## poly(arr_charges_d$Arrests, 3)3  41.7797     8.0786   5.172 6.65e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 8.079 on 165 degrees of freedom
## Multiple R-squared:  0.4919, Adjusted R-squared:  0.4826 
## F-statistic: 53.24 on 3 and 165 DF,  p-value: < 2.2e-16

So the correlation between Arrests and Percent of Town in the Buffer zone?

0.5982812

That’s a strong positive relationship.

Just to compare, let’s look at the relationship between Arrests and town population

ug <- ggplot(arr_charges_d, aes(x=Population, y=Arrests)) +
  geom_point(aes(text=Town)) +
  geom_smooth(method=lm,  formula = y ~ poly(x, 2), size=1) +
  theme_minimal() 
ug <- ug + ggtitle("Number of arrests versus population of town")
ug <- ug + labs(x="Population", y="Arrests for 279(d) since 1999")
#ug

qy <- plotly()
qy$ggplotly(ug,session="knitr", kwargs=list(layout=list(hovermode="closest", filename="arrests-279d", fileopt="overwrite")))

Some choropleth maps with the data

Percent of town in a buffer zone

Arrests per capita

Here’s a table to explore further.

The correlation between Arrests and Town population: 0.6233308

That’s a slightly stronger positive relationship than buffer zone size.

Visualizing the zones where suspects can get charged for 21a-278b

Statute 21a-278b expands on the day cares and school zones by adding about 2,000 public housing units.

The additional 2,000 housing spots expands the the density of the buffer zones across the state, most notably in towns like Waterbury, New Haven, and Bridgeport.

The relationship between number of arrests and percent of town in buffer

library(ctnamecleaner)
## 
## Attaching package: 'ctnamecleaner'
## 
## The following object is masked _by_ '.GlobalEnv':
## 
##     pop
all_arrests <- read.csv("arrests.csv")
b278_all <- filter(all_arrests, ORIGINAL.STATUTE=="21a-278a(b)")
b278_all <- ctnamecleaner(Town, b278_all)
## Joining by: "name2"
## [1] "...All names matched. That's a rare thing."
b278_count <- data.frame(table(b278_all$real.town.name))
colnames(b278_count) <- c("Town","arrests")
b278 <- left_join(b278, b278_count)
## Joining by: "Town"
## Warning in left_join_impl(x, y, by$x, by$y): joining factor and character
## vector, coercing into character vector
b278 <- left_join(b278, pop)
## Joining by: "Town"
b278$Arrests.Per.Capita <- (b278$arrests/b278$Population)*1000
b278$Arrests.Per.Capita <- round(b278$Arrests.Per.Capita, digits=2)

b278 <- na.omit(b278)


bplot <- ggplot(b278, aes(x=Percent.of.town.in.buffer, y=arrests)) +
  geom_point(aes(text=Town)) +
  geom_smooth(method=lm, formula = y ~ poly(x, 3), size=1) +
  theme_minimal() +
  ggtitle("Number of arrests versus percent of Buffer zone") %>%
  labs(x="Percent of town in buffer", y="Arrests for 278(b) since 1999")
#bplot
ry <- plotly()
ry$ggplotly(bplot,session="knitr", kwargs=list(layout=list(hovermode="closest", filename="buffer-278b", fileopt="overwrite")))

Just to compare, let’s look at the relationship between Arrests and town population

bpplot <- ggplot(b278, aes(x=Population, y=arrests)) +
  geom_point(aes(text=Town)) +
  geom_smooth(method=lm, formula = y ~ poly(x, 3), size=1) +
  theme_minimal() +
  ggtitle("Number of arrests versus percent of Buffer zone") %>%
  labs(x="Town population", y="Arrests for 278(b) since 1999")
#bpplot
py <- plotly()
py$ggplotly(bpplot,session="knitr", kwargs=list(layout=list(hovermode="closest", filename="arrests-278b", fileopt="overwrite")))

Some choropleth maps with the data

Percent of town in a buffer zone

Arrests per capita